package com.neulogistics.core.customercenter.api.application.command.handler;

import com.blackto.lib.mediat.unicast.IRequestHandler;
import com.neulogistics.core.customercenter.api.application.command.PlaceOrderCommand;
import com.neulogistics.core.customercenter.api.application.command.ReturnOrderCommand;
import com.neulogistics.core.customercenter.api.application.integrationevent.ICustomerCenterIntegrationEventService;
import com.neulogistics.core.customercenter.api.application.integrationevent.publish.OrderPlacedIntegrationEvent;
import com.neulogistics.core.customercenter.api.application.integrationevent.publish.OrderReturnedIntegrationEvent;
import com.neulogistics.core.customercenter.api.application.rpc.ICustomerCenterRPC;
import com.neulogistics.core.customercenter.api.service.ThreadLocalService;
import com.neulogistics.core.customercenter.domain.model.aggregate.Order;
import com.neulogistics.core.customercenter.domain.model.enumeration.OrderStatus;
import com.neulogistics.core.customercenter.domain.model.enumeration.OrderType;
import com.neulogistics.core.customercenter.domain.model.valueobject.Address;
import com.neulogistics.core.customercenter.domain.model.valueobject.OrderItem;
import com.neulogistics.core.customercenter.domain.repository.IOrderRepository;
import com.neulogistics.core.customercenter.domain.service.ICustomerCenterDomainService;
import com.neulogistics.infrastructure.cache.idservice.RedisIdUtil;
import com.neulogistics.infrastructure.common.annotation.ProduceEvent;
import com.neulogistics.infrastructure.common.serviceresult.BaseResponse;
import com.neulogistics.infrastructure.common.serviceresult.ErrorCode;
import com.neulogistics.infrastructure.common.serviceresult.ResultUtils;
import com.neulogistics.infrastructure.integrationeventlog.model.IntegrationEventConstant;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Component
public class ReturnOrderCommandHandler implements IRequestHandler<ReturnOrderCommand, BaseResponse<Long>> {
    @Resource
    IOrderRepository orderRepository;

    @Resource
    ICustomerCenterRPC customerCenterRPC;

    @Resource
    ICustomerCenterIntegrationEventService customerCenterIntegrationEventService;

    @Resource
    RedisIdUtil redisIdUtil;

    @Value("${spring.application.name}")
    private String appName;

    private final String Order_Id_Key;

    @Resource
    private TransactionTemplate transactionTemplate;

    public ReturnOrderCommandHandler(@Value("${spring.application.name}") String appName) {
        Order_Id_Key = appName + ":" + "orderId";
    }

    @Override
    @ProduceEvent
    public BaseResponse<Long> handle(ReturnOrderCommand command) {
        // 根据订单id查询需要退货的订单
        Order oldOrder = orderRepository.findById(command.orderId);

        // 查询订单是否已完成
        Boolean completed = oldOrder.getOrderStatus() == OrderStatus.Completed;
        if(!completed){
            return ResultUtils.error(ErrorCode.PARAMS_ERROR, "订单状态异常。");
        }

        // 查询订单项是否支持退货
        Integer goodsId = oldOrder.getOrderItems().get(0).getGoodsId();
        Boolean canReturn = customerCenterRPC.checkGoodsCanReturn(goodsId);
        if(!canReturn){
            return ResultUtils.error(ErrorCode.PARAMS_ERROR, "该商品不支持退货。");
        }

        // 依据老订单创建新退货单
        Long orderId = redisIdUtil.nextId(Order_Id_Key);
        Integer customerId = oldOrder.getCustomerId();
        List<OrderItem> orderItems = oldOrder.getOrderItems();
        String orderRemark = oldOrder.getOrderRemark();
        Address receiverAddress = oldOrder.getReceiverAddress();
        String receiverName = oldOrder.getReceiverName();
        String receiverPhone = oldOrder.getReceiverPhone();

        Order returnOrder = new Order(orderId, OrderType.Return, customerId, orderItems,
                orderRemark, receiverAddress, receiverName,
                receiverPhone, 0, null);

        // 老订单置为已退货
        oldOrder.setOrderStatus(OrderStatus.Returned);

        // 开启事务
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
            try {
                // 持久化
                orderRepository.save(returnOrder);
                orderRepository.save(oldOrder);

                // 生成集成事件id并创建事件
                Long eventId = redisIdUtil.nextId(IntegrationEventConstant.Integration_Event_Id_Key);
                OrderReturnedIntegrationEvent orderReturnedIntegrationEvent = new OrderReturnedIntegrationEvent(eventId);
                BeanUtils.copyProperties(returnOrder, orderReturnedIntegrationEvent);

                // 获取当前事务id，并保存该集成事件
                Long transactionId = ThreadLocalService.transactionId.get();
                customerCenterIntegrationEventService.addAndSaveEvent(orderReturnedIntegrationEvent, transactionId);
            } catch (Exception e){
                // 触发回滚
                throw new RuntimeException(e.getMessage());
            }
            }
        });

        return ResultUtils.success(orderId);
    }
}
